﻿// Inner Fire 游戏引擎库
// DxDraw 渲染器帧资源管理
//
// Copyright (c) 2025 by 尔西大帝. All rights reserved.
//
// 用于DirectX的渲染器。
// 此文件分装用于帧资源管理功能。
//
// Author: 尔西大帝
// Email: 2670613871@qq.com
// Created: 2025-04-24

#include "dx_frame_resource.h"
#include "dx_graphics.h"

namespace ifire::dx {
void DxFrameResource::InitConfig() {
  auto& cfg = dx_->Config()["FrameResource"];

  // 初始化Frame的Description，用于以后的初始化
  desc.PassCount = 1;
  desc.ShadowPassCount = 1;
  desc.ObjectCount = cfg("Object", 1024);
  desc.SkinnedObjectCount = cfg("SkinnedObject", 32);
  desc.MaterialCount = cfg("Material", 256);
  desc.UICount = cfg("UIImage", 1024);
  desc.TextCount = cfg("UIText", 1024);
  desc.InstancedSprite = cfg("InstancedSprite", 128);
  desc.MapBlock = cfg("MapBlock", 128);
}

void DxFrameResource::BuildFrameResources() {
  for (int i = 0; i < FRAME_RESOURCE_COUNT; i++) {
    frame_resources_.push_back(
        std::make_unique<FrameResource>(dx_->Device(), desc));
  }
}

void DxFrameResource::SwitchFrameResource() {
  // 循环往复地获得帧资源循环数组中的元素
  frame_res_idx_ = (frame_res_idx_ + 1) % FRAME_RESOURCE_COUNT;
  curr_frame_res_ = frame_resources_[frame_res_idx_].get();

  // 当前的这个帧资源是否还有未执行完的命令？如果有，则令其执行到这个围栏点
  auto fence = dx_->GetFence();
  if (curr_frame_res_->Fence != 0 &&
      fence->GetCompletedValue() < curr_frame_res_->Fence) {
    HANDLE handle = CreateEventEx(nullptr, NULL, false, EVENT_ALL_ACCESS);
    HASSERT(fence->SetEventOnCompletion(curr_frame_res_->Fence, handle));
    WaitForSingleObject(handle, INFINITE);
    CloseHandle(handle);
  }
}

int DxFrameResource::CreateInstancedBuffer(size_t count) {
  int index = 0;

  // 因为每一次都是三个一起创建，所有Index都是一样的。
  for (auto& e : frame_resources_) {
    index = e->instanced_sprite.Add(dx_->Device(), count);
  }

  return index;
}

} // namespace ifire::dx